﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BasketTrader.cs" company="">
//   
// </copyright>
// <summary>
//   The agressor.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Linq;
using Systemathics.FrameWork;
using Systemathics.Indicators;

namespace Systemathics.Automates
{
    [Pattern("Systemathics.Automates.Agressor.dll", "1.0")]
    [GUI("Systemathics.Trader", "1.0")]
    [SetBars(BarType.Seconds, 60)]
    public sealed partial class Agressor : Strategy
    {
        private const int LENGTH = 5;
        private const double SIGMA = 1.7;
        private const int MAX_REJECTION = 5;

        private BBD BBD;
        private BBU BBU;
        private BarSeries BarSeries;

        private SystemathicsSound sounds;

        private Guid SignalOrder;
        private Guid TakeProfitOrder;
        private Guid StopLossOrder;

        public override void OnStart()
        {
            sounds = new SystemathicsSound();
            var i = Instruments.Values.FirstOrDefault();
            i.CustomValue1 = i.CustomValue2 = 0;
            BBU = new BBU(i, Data.Bar, BarType.Seconds, 60 , LENGTH, SIGMA);
            BBD = new BBD(i, Data.Bar, BarType.Seconds, 60, LENGTH, SIGMA);
            BarSeries = new BarSeries(i.StaticData.Name);

            GetHistoricalData(i, DateTime.Today.AddDays(-4), DateTime.Today,Data.Bar,600,DataSource.CurrentDataProvider);

            base.OnStart();
        }
        public override void OnBarClose(Bar t)
        {
            if (BBU.Count() > 0)
            {
                if (Instruments[t.Id].isFlat)
                {
                    if (BarSeries.Crosses(BBU) == Cross.Below)
                        SignalOrder = Sell(t.Id, OrderStyle.Limit, t.Median, 2000, new OrderExtension { Tif = TimeInForce.ImmediateOrCancel });

                    else if (BarSeries.Crosses(BBD) == Cross.Above)
                        SignalOrder = Buy(t.Id, OrderStyle.Limit, t.Median, 2000, new OrderExtension { Tif = TimeInForce.ImmediateOrCancel });
                }
                Instruments[t.Id].CustomValue2 = BBU.Last();
                Instruments[t.Id].CustomValue1 = BBD.Last();
            }
            BarSeries.Add(t);
        }
        public override void OnBarOpen(Bar t)
        {
        }
        public override void OnTrade(Trade t)
        {
           
        }
        public override void OnBlotter(Blotter blotter)
        {
        }
        public override void OnMarketData(MarketData marketdata)
        {
        }
        public override void OnOrder(Order o)
        {
            switch (o.Status)
            {
                case OrderStatus.ACK:
                    sounds.ACK();
                    break;
                case OrderStatus.ACK_CANCEL:
                    sounds.ACK_CANCEL();
                    break;
                case OrderStatus.ACK_MODIFY:
                    sounds.ACK_MODIFY();
                    break;
                case OrderStatus.FILLED:
                    sounds.FILLED();
                    Hedge(o);
                    break;
                case OrderStatus.PARTIALLY_FILLED:
                    sounds.PARTIALLY_FILLED();
                    break;
                case OrderStatus.REJECT:
                    ReSend(o.Id);
                    break;
                case OrderStatus.REJECT_CANCEL:
                    ReSend(o.Id);
                    break;
                case OrderStatus.REJECT_MODIFY:
                    break;
            }
        }
        public override void OnMoneyManagement(MoneyManagement mm)
        {
        }
        public override void OnTradeSeries(TradeSeries series)
        {
        }
        public override void OnQuoteSeries(QuoteSeries series)
        {
        }
        public override void OnBarSeries(BarSeries series)
        {
            Draw(series);
        }
        public override void OnUnBuild()
        {
            // Lock the OnBarOpenSending Signal and begin to fltten position intelligentely
        }
        public override void OnBuild()
        {
        }
        public override void OnStop()
        {
            CancelAllStrategyOrders();
            SweepToFill(Expo.Traded);
            //if no cancel rejected and swepp ok
            base.OnStop();
        }

        #region private

        private void Hedge(Order o)
        {
            if (o.Id == SignalOrder)
            {
                Decimal StopTarget = 0m;
                Decimal ProfitTarget = 0m;
                switch (o.Side)
                {
                    //stop orders must be programmed in VM, otherwise it wont work as it is below
                    case OrderSide.Buy:
                        StopTarget = BBD.LastMean - (Decimal)(2 * SIGMA * BBD.LastSigma);
                        ProfitTarget = BBD.LastMean;
                        TakeProfitOrder = Sell(o.InstrumentId, OrderStyle.Limit, ProfitTarget, o.TotalExecutedQuantity, new OrderExtension { Tif = TimeInForce.FillOrKill, ParentOrderId = SignalOrder });
                        StopLossOrder = Sell(o.InstrumentId, OrderStyle.StopLimit, StopTarget, o.TotalExecutedQuantity, new OrderExtension { Tif = TimeInForce.FillOrKill, ParentOrderId = SignalOrder });
                        break;
                    case OrderSide.Sell:
                        StopTarget = BBU.LastMean + (Decimal)(2 * SIGMA * BBU.LastSigma);
                        ProfitTarget = BBU.LastMean;
                        TakeProfitOrder = Buy(o.InstrumentId, OrderStyle.Limit, ProfitTarget, o.TotalExecutedQuantity, new OrderExtension { Tif = TimeInForce.FillOrKill, ParentOrderId = SignalOrder });
                        StopLossOrder = Buy(o.InstrumentId, OrderStyle.StopLimit, StopTarget, o.TotalExecutedQuantity, new OrderExtension { Tif = TimeInForce.FillOrKill, ParentOrderId = SignalOrder });
                        break;
                }
            }
            else if(o.Id == TakeProfitOrder)
            {
                Cancel(StopLossOrder); // oca

            }
            else if(o.Id == StopLossOrder)
            {
                Cancel(TakeProfitOrder); //reject cancel
            }
        }

        #endregion
    }
}